import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;

class Main {
    private static void printPermutations(List<Genome> genomes, String filename) throws IOException {
        PrintWriter writer = new PrintWriter(filename);
        for (Genome genome : genomes) {
            writer.println(genome.getName());
            for (int i = 0; i < genome.blockCount(); i++) {
                int block = genome.getBlock(i);
                if (block > 0) writer.print("+");
                writer.print(genome.getBlock(i) + " ");
            }
            writer.println("$");
        }
        writer.close();
    }

    private static void saveScenario(Stack<Command> commands, String filename) throws IOException {
        PrintWriter writer = new PrintWriter(filename);
        for (Command command : commands) {
            writer.println(command.toString());
        }
        writer.close();
    }

    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            System.err.println("Please use the --help option to get usage information");
            return;
        }
        if (args.length == 1 && (args[0].equals("--help") || args[0].equals("-h"))) {
            System.err.println("Usage: rearrangement-simulator <input-file>");
            System.err.println("Use interactive command \"help\" to get usage information for interactive commands");
            return;
        }
        if (args.length == 1 && args[0].equals("--version")) {
            System.err.println("rearrangement-simulator v1.01");
            return;
        }
        List<Genome> genomes;
        try {
            genomes = PermutationReader.readGenomes(args[0]);
        } catch (IOException e) {
            System.err.println("Cannot read the file");
            return;
        }
        Scanner in = new Scanner(System.in);
        CommandParser commandParser = new CommandParser(genomes);

        Stack<Command> undoCommands = new Stack<>();
        Stack<Command> redoCommands = new Stack<>();

        while (true) {
            System.out.print("> ");
            String cmd = in.nextLine().trim();
            if (cmd.equals("exit")) {
                break;
            } else if (cmd.startsWith("?")) {
            	try {
            		System.err.print(CommandUsage.getUsageInfo(cmd));
            	} catch (CommandFormatException cfe) {
            		System.err.println("Invalid command: " + cfe.getMessage());
            	}
            } else if (cmd.equals("help")) {
                System.err.println("Type ?<command> to get usage infromation for one of these available commands:");
                System.err.println();
                System.err.println("\tinsert");
                System.err.println("\tdelete");
                System.err.println("\treverse");
                System.err.println("\ttransposition");
                System.err.println("\tundo");
                System.err.println("\tredo");
                System.err.println("\tsave");
                System.err.println("\tsave_scenario");
                System.err.println("\texit");
                System.err.println("\thelp");
            } else if (cmd.equals("undo")) {
                if (undoCommands.empty()) {
                    System.err.println("Nothing to undo");
                } else {
                    redoCommands.push(undoCommands.peek());
                    undoCommands.pop().undo();
                }
            } else if (cmd.equals("redo")) {
                if (undoCommands.empty()) {
                    System.err.println("Nothing to redo");
                } else {
                    undoCommands.push(redoCommands.peek());
                    redoCommands.pop().execute();
                }
            } else if (cmd.startsWith("save_scenario ")) {
                String filename = cmd.substring(14);
                try {
                    saveScenario(undoCommands, filename);
                } catch (IOException e) {
                    System.err.println("Couldn't write to file " + filename);
                }
            } else if (cmd.startsWith("save ")) {
                String filename = cmd.substring(5);
                try {
                    printPermutations(genomes, filename);
                } catch (IOException e) {
                    System.err.println("Couldn't write to file " + filename);
                }
            } else {
                try {
                    Command command = commandParser.parseCommand(cmd);
                    command.execute();
                    redoCommands.clear();
                    undoCommands.add(command);
                } catch (CommandFormatException cfe) {
                    System.err.println("Invalid command: " + cfe.getMessage());
                } catch (ParametersException pe) {
                    System.err.println("Error: " + pe.getMessage());
                }
            }
        }
    }
}
